package com.tapstitch.scm.common.utils;

import cn.hutool.core.date.DateUtil;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * 时区时间格式转化
 * @author zhenyu.guo
 * @date 2018/8/28.
 */
public class TimeZoneUtil {

    public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
    public static final String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";


    public static final String yyyy_MM_dd_T_HH_mm_ss = "yyyy-MM-dd'T'HH:mm:ss";

    public static final String YYYY_MM_DD_HH_MM_SS_Z = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    public static final String yyyy_MM_dd = "yyyy-MM-dd";
    public static final String yyyyMMdd = "yyyyMMdd";

    public static final String mm_dd_yyyy = "MM/dd/yyyy";

    private static final DateTimeFormatter DATE_TIME_FORMATTER =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final DateTimeFormatter DATE_HOUR_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 将系统本地时间转换成中国时间
     * @param date
     * @return
     */
    public static String localDate2ChineseDateStr(Date date) {
    	if (Objects.isNull(date)) {
    		return null;
    	}
    	return dateToStrTimeZone(date, TimeZoneEnum.CHINESE);
    }

    /**
     * 将系统本地时间转换成中国时间
     * @param date
     * @return
     */
    public static String localDate2ChineseDateStrFormat(Date date, String dateFormat) {
        if (Objects.isNull(date)) {
            return null;
        }
        return dateToStrTimeZone(date, TimeZoneEnum.CHINESE, dateFormat);
    }

    /**
     * 将系统本地时间转换成中国时间
     * @param localDate
     * @return
     */
    public static String localDate2ChineseDateStr(Date localDate, String format) {
    	if (Objects.isNull(localDate)) {
    		return null;
    	}
    	return  new DateTime(localDate, DateTimeZone.forID(TimeZoneEnum.CHINESE.getValue())).toString(format);

    }

    /**
     * 将时间戳转换成中国时间
     * @param timestamp
     * @return
     */
    public static String timestamp2ChineseDateStr(Long timestamp) {
        return timestamp2ChineseDateStr(timestamp, TimeUnit.SECONDS, yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 将时间戳转换成中国时间
     * @param timestamp
     * @return
     */
    public static String timestamp3ChineseDateStr(Long timestamp) {
        return timestamp2ChineseDateStr(timestamp, TimeUnit.SECONDS, yyyy_MM_dd);
    }

    /**
     * 将时间戳转换成中国时间
     * @param timestamp
     * @param timeUnit
     * @return
     */
    public static String timestamp2ChineseDateStr(Long timestamp, TimeUnit timeUnit) {
        return timestamp2ChineseDateStr(timestamp, timeUnit, yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 将时间戳转换成中国时间
     *
     * @param timestamp 时间戳
     * @param timeUnit
     * @param format    格式
     * @author wuqiong 2019-07-17 12:03
     */
    public static String timestamp2ChineseDateStr(Long timestamp, TimeUnit timeUnit, String format) {
        if (Objects.isNull(timestamp)) {
            return null;
        }
        Long ms = timeUnit.toMillis(timestamp);
        return new DateTime(ms, DateTimeZone.forID(TimeZoneEnum.CHINESE.getValue())).toString(format);
    }



    public static void main(String[] args) {

//        Long times = 1683251299000L;
//        Date date = new Date(times);
//        SimpleDateFormat sdfAmerica = new SimpleDateFormat("MM/dd/yyyy");
//        String sDateInAmerica = sdfAmerica.format(new Date(times));
//
//        System.out.println(sDateInAmerica);


        //System.out.println(timestamp2ChineseDateStr(System.currentTimeMillis(), TimeUnit.MILLISECONDS, yyyyMMdd));
//        System.out.println(timestamp2ChineseDateStr(System.currentTimeMillis(), TimeUnit.MILLISECONDS, yyyy_MM_dd_HH_mm_ss));

//    	chineseDateStr2LocalDate(String)
//    	chineseDateStr2LocalDateStr(String)
//    	dateToStrTimeZone(Date, TimeZoneEnum)
//    	localDate2ChineseDateStr(Date)
//    	DateTime dateTime = new DateTime(2019, 3, 9, 10, 9, 11);
//    	System.out.println(chineseDateStr2LocalDate("2019-03-10 02:09:11"));
//    	System.out.println(chineseDateStr2LocalDateStr("2019-03-10 02:09:11"));
//    	System.out.println(dateToStrTimeZone(dateTime.toDate(), TimeZoneEnum.CHINESE));
//    	System.out.println(localDate2ChineseDateStr(dateTime.toDate()));
//    	System.err.println(timestamp2ChineseDateStr(1551628800L, TimeUnit.SECONDS));
//        System.err.println(chineseDateStr2Timestamp("2019-03-04 00:00:00", TimeUnit.SECONDS));
//        String chineseDateStr = TimeZoneUtil.localDate2ChineseDateStr(new Date(), TimeZoneUtil.yyyy_MM_dd);
//    	System.out.println(chineseDateStr);
//		Date todayMorningOfChinese = TimeZoneUtil.chineseDateStr2LocalDate("2019-06-29 00:00:00");
//		String str = new DateTime().toString("yyyy-MM-dd HH:mm:ss", Locale.US);
//        System.out.println(str);
    }
//
//    /**
//     * 将系统本地时间转换成中国时间
//     * @param date
//     * @return
//     */
//    public static Date localDate2ChineseDate(Date date) {
//        if (Objects.isNull(date)) {
//            return null;
//        }
//        return new DateTime(date.getTime(), DateTimeZone.forID(TimeZoneEnum.CHINESE.getValue())).toDate();
//    }


    /**
     * 将中国时间转换成系统本地时间
     * @param chineseDateStr: 中国时间 yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static Date chineseDateStr2LocalDate(String chineseDateStr) {
        return chineseDateStr2LocalDate(chineseDateStr, yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 将中国时间转换成系统本地时间
     * @return
     */
    public static Long chineseDateStr2LocalDate(Date date) {
        return chineseDateStr2LocalDate(DateUtil.format(date, yyyy_MM_dd_HH_mm_ss)).getTime()/1000;
    }

    /**
     * 将中国时间转换成系统本地时间
     * @param chineseDateStr: 中国时间 yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static Date chineseDateStr2LocalDate(String chineseDateStr, String format) {
        return dateStr2LocalDate(chineseDateStr, format, TimeZoneEnum.CHINESE);
    }

    public static Date dateStr2LocalDate(String chineseDateStr, String format, TimeZoneEnum timeZone) {
        if (StringUtils.isEmpty(chineseDateStr)) {
            return null;
        }
        DateTime parse = DateTime.parse(chineseDateStr, DateTimeFormat.forPattern(format).withZone(DateTimeZone.forID(timeZone.getValue())));
        return parse.toDate();
    }

    /**
     * 将中国时间转换成系统本地时间
     * @param chineseDateStr: 中国时间 yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String chineseDateStr2LocalDateStr(String chineseDateStr) {
        if (Objects.isNull(chineseDateStr)) {
            return null;
        }
        Date localDate = TimeZoneUtil.chineseDateStr2LocalDate(chineseDateStr);
        return new DateTime(localDate).toString(yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 将中国时间转换成时间戳
     * @param chineseDateStr
     * @param timeUnit
     * @return
     */
    public static Long chineseDateStr2Timestamp(String chineseDateStr, TimeUnit timeUnit) {
        Date localDate = TimeZoneUtil.chineseDateStr2LocalDate(chineseDateStr);
        return timeUnit.convert(localDate.getTime(), TimeUnit.MILLISECONDS);
    }

    /**
     * 将中国时间转换成时间戳
     * @param chineseDateStr
     * @param timeUnit
     * @return
     */
    public static Long chineseDateStr2Timestamp(String chineseDateStr, TimeUnit timeUnit, String format) {
        Date localDate = TimeZoneUtil.chineseDateStr2LocalDate(chineseDateStr, format);
        return localDate == null ? null : timeUnit.convert(localDate.getTime(), TimeUnit.MILLISECONDS);
    }

    public static Long dateStr2Timestamp(String chineseDateStr, TimeUnit timeUnit, String format, TimeZoneEnum timeZone) {
        Date localDate = dateStr2LocalDate(chineseDateStr, format, timeZone);
        return timeUnit.convert(localDate.getTime(), TimeUnit.MILLISECONDS);
    }

    public static Long dateStr2Timestamp(String chineseDateStr, TimeUnit timeUnit, TimeZoneEnum timeZone) {
        return dateStr2Timestamp(chineseDateStr, timeUnit, yyyy_MM_dd_HH_mm_ss, timeZone);
    }

    public static String dateToStrTimeZone(Date date, TimeZoneEnum zone) {
        return new DateTime(date, DateTimeZone.forID(zone.getValue())).toString(yyyy_MM_dd_HH_mm_ss);
    }

    public static String dateToStrTimeZone(Date date, TimeZoneEnum zone, String format) {
        return new DateTime(date, DateTimeZone.forID(zone.getValue())).toString(format);
    }

    public static long[] getWeekStarAndEndTime() {
// 使用Calendar类
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK,  Calendar.MONDAY);
        cal.set(Calendar.HOUR_OF_DAY,  0);
        cal.set(Calendar.MINUTE,  0);
        cal.set(Calendar.SECOND,  0);
        long weekStartTime = cal.getTimeInMillis() / 1000;
        cal.add(Calendar.DATE,  6);
        cal.set(Calendar.HOUR_OF_DAY,  23);
        cal.set(Calendar.MINUTE,  59);
        cal.set(Calendar.SECOND,  59);
        long weekEndTime = cal.getTimeInMillis()/1000;
        return new long[]{weekStartTime, weekEndTime};
    }

    /**
     * 获取最近两周的时间，周一开始，周日结束
     * @return
     */
    public static String[] getLastTwoWeekRange() {
        LocalDateTime now = LocalDateTime.now();

        // 获取本周周一
        LocalDateTime monday = now.minusWeeks(1).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
                .withHour(0).withMinute(0).withSecond(0).withNano(0);

        // 获取本周周日
        LocalDateTime sunday = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY))
                .withHour(23).withMinute(59).withSecond(59).withNano(0);

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        return new String[]{monday.format(formatter), sunday.format(formatter)};
    }


    public static String[] getCurrentWeekRange() {
        LocalDateTime now = LocalDateTime.now();

        // 获取本周周一
        LocalDateTime monday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
                .withHour(0).withMinute(0).withSecond(0).withNano(0);

        // 获取本周周日
        LocalDateTime sunday = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY))
                .withHour(23).withMinute(59).withSecond(59).withNano(0);

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        return new String[]{monday.format(formatter), sunday.format(formatter)};
    }

    /**
     * 根据起始日期和结束日期，生成每周的时间戳范围（秒级）
     * @param startDate 起始日期时间
     * @param endDate 结束日期时间
     * @return Map<String, long[]> 键为"yyyy-MM-dd~yyyy-MM-dd"格式的周范围，值为long[开始时间戳（秒）, 结束时间戳（秒）]
     */
    public static Map<String, long[]> generateWeeklyTimestamps(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, long[]> weeklyTimestamps = new LinkedHashMap<>();
        ZoneId zoneId = ZoneId.systemDefault();

        LocalDateTime currentMonday = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDateTime lastDay = endDate.withHour(23).withMinute(59).withSecond(59).withNano(999999999);

        while (!currentMonday.isAfter(lastDay))  {
            LocalDateTime weekStart = currentMonday.withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime weekEnd = currentMonday.plusDays(6).withHour(23).withMinute(59).withSecond(59).withNano(999999999);

            // 如果周结束时间超过了结束日期，则使用结束日期
            if (weekEnd.isAfter(lastDay))  {
                weekEnd = lastDay;
            }

            // 获取秒级时间戳（Unix Timestamp）
            long startTimestamp = weekStart.atZone(zoneId).toEpochSecond();
            long endTimestamp = weekEnd.atZone(zoneId).toEpochSecond();

            String weekRange = weekStart.toLocalDate()  + "~" + weekEnd.toLocalDate();
            weeklyTimestamps.put(weekRange,  new long[]{startTimestamp, endTimestamp});

            currentMonday = currentMonday.plusWeeks(1);
        }

        return weeklyTimestamps;
    }

    /**
     * 根据 yyyy-MM-dd 格式的时间字符串，返回当天 00:00:00 的时间戳（秒级）
     * @param dateStr 格式："2025-04-01"
     * @return 返回当天 0 点的秒级时间戳（Unix timestamp）
     */
    public static long getDayStartTimestamp(String dateStr) {
        // 解析 yyyy-MM-dd 日期
        LocalDate date = LocalDate.parse(dateStr,  DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 转换成当天 00:00:00 的 LocalDateTime
        LocalDateTime startOfDay = date.atStartOfDay();

        // 转换为秒级时间戳（可选：根据你的需求返回毫秒或秒）
        return startOfDay.toEpochSecond(ZoneOffset.ofHours(8));
    }

    /**
     * 返回传入日期当天的 23:59:59 时间戳（秒级）
     * @param dateStr 格式："2025-04-01"
     * @return 秒级时间戳（Unix timestamp）
     */
    public static long getDayEndTimestamp(String dateStr) {
        // 解析 yyyy-MM-dd 日期
        LocalDate date = LocalDate.parse(dateStr,  DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 转换成当天 23:59:59 的 LocalDateTime
        LocalDateTime endOfDay = date.atTime(LocalTime.MAX);

        // 转换为秒级时间戳
        return endOfDay.toEpochSecond(ZoneOffset.ofHours(8));
    }

    public static long convertToTimestamp(String timeStr) throws IllegalArgumentException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setLenient(false);  // 严格模式，确保时间有效性

        try {
            Date date = sdf.parse(timeStr);
            return date.getTime()  / 1000;
        } catch (ParseException e) {
            throw new IllegalArgumentException("时间格式不正确，请输入yyyy-MM-dd HH:mm:ss格式的时间字符串", e);
        }
    }

    /**
     * 获取最近90天的开始时间和结束时间（按天数精确计算）
     * @return String[] 数组，[0]=开始时间，[1]=结束时间
     */
    public static String[] getLastDaysRange(Long day) {
        LocalDate today = LocalDate.now();

        // 计算90天前的日期
        LocalDate startDate = today.minusDays(day);

        // 开始时间 (00:00:00)
        LocalDateTime startDateTime = startDate.atStartOfDay();

        // 结束时间 (23:59:59)
        LocalDateTime endDateTime = today.atTime(23,  59, 59);

        return new String[]{
                startDateTime.format(DATE_TIME_FORMATTER),
                endDateTime.format(DATE_TIME_FORMATTER)
        };
    }
    public static String getFormattedWeekWithoutDay(String dateStr) {
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd");
        LocalDateTime endOfDay = LocalDate.parse(dateStr,  inputFormatter).atTime(LocalTime.MAX);

        // 获取 ISO 周数和年份
        int year = endOfDay.get(WeekFields.ISO.weekBasedYear());
        int week = endOfDay.get(WeekFields.ISO.weekOfWeekBasedYear());

        // 手动格式化为 "YYYY-Www"
        return String.format("%04d-W%02d",  year, week);
    }

    /**
     * 获取当前日期的ISO年周格式（YYYY-Www）
     * @return 例如 "2025-W17"
     */
    public static String getCurrentIsoWeekYear() {
        // 1. 获取美西当前时间（考虑夏令时）
        ZoneId losAngelesZone = ZoneId.of("America/Los_Angeles");
        ZonedDateTime losAngelesTime = ZonedDateTime.now(losAngelesZone);

        // 2. 加16小时
        ZonedDateTime adjustedTime = losAngelesTime.plusHours(16);
        LocalDate adjustedDate = adjustedTime.toLocalDate();
        int year = adjustedDate.get(WeekFields.ISO.weekBasedYear());  // 基于周的年份
        int week = adjustedDate.get(WeekFields.ISO.weekOfWeekBasedYear());  // ISO周数
        return String.format("%04d-W%02d",  year, week);
    }

    /**
     * 生成某一天按小时划分的时间点集合（前23小时为整点，最后一小时为23:59）
     * @param date 目标日期（如 LocalDate.of(2025,  1, 1)）
     * @return 时间点字符串列表（格式："2025-01-01 00:00"）
     */
    public static List<String> getHourlyTimePointsWithLastMinute(LocalDate date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        return IntStream.range(0,  24)
                .mapToObj(hour -> {
                    if (hour < 23) {
                        return date.atTime(hour,  0).format(formatter);  // 00:00, 01:00, ..., 22:00
                    } else {
                        return date.atTime(23,  59).format(formatter);    // 23:59
                    }
                })
                .collect(Collectors.toList());
    }

    public static List<String> generateHourlyTimeSlots(LocalDateTime startDate, Integer hour) {
        List<String> timeSlots = new ArrayList<>();

        // 从当天的01:00开始
        LocalDateTime start = startDate.withHour(hour).withMinute(0);
        // 到次日的00:00结束
        LocalDateTime end = startDate.plusDays(1).withHour(0).withMinute(0);

        LocalDateTime current = start;
        while (current.isBefore(end))  {
            timeSlots.add(current.format(DATE_HOUR_FORMATTER));
            current = current.plusHours(1);
        }

        // 添加次日的00:00
        timeSlots.add(end.format(DATE_HOUR_FORMATTER));

        return timeSlots;
    }

    public static String generateCurrentHourly() {
        return LocalDateTime.now(ZoneId.of("America/Los_Angeles"))
                .atZone(ZoneId.of("America/Los_Angeles"))
                .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                .plusHours(1)
                .truncatedTo(ChronoUnit.HOURS)
                .format(DATE_HOUR_FORMATTER);
    }


    public static Long convertToTimestampSecond(cn.hutool.core.date.DateTime date, TimeZoneEnum timeZone) {
        String localDateTimeStr = DateUtil.format(date, yyyy_MM_dd_HH_mm_ss);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(localDateTimeStr, formatter);
        ZoneId zoneId = ZoneId.of(timeZone.getValue());
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
        return zonedDateTime.toInstant().getEpochSecond();
    }

    /**
     * 根据开始日期和结束日期获取时间范围
     * @param startDate 开始日期（格式：yyyy-MM-dd）
     * @param endDate 结束日期（格式：yyyy-MM-dd）
     * @return 包含开始时间（00:00:00）和结束时间（23:59:59）的数组
     */
    public static String[] getDateRange(String startDate, String endDate) throws DateTimeParseException {
        // 解析开始日期并设置时间为00:00:00
        LocalDate start = LocalDate.parse(startDate,  DATE_FORMATTER);
        String startDateTime = start.atStartOfDay().format(DATE_TIME_FORMATTER);

        // 解析结束日期并设置时间为23:59:59
        LocalDate end = LocalDate.parse(endDate,  DATE_FORMATTER);
        String endDateTime = end.atTime(23,  59, 59).format(DATE_TIME_FORMATTER);

        return new String[]{startDateTime, endDateTime};
    }

}
